import json
import re

from django.contrib.auth import logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages import constants
from django.shortcuts import render
from django.utils import http
from django.views import View
from django.core.cache import cache
from django.http import JsonResponse
# Create your views here.
from apps.users.models import Address
from utils.views import LoginRequiredJSONMixin

"""
需求：
    获取省份信息
前端：
    当页面加载的时候，会发送axios请求，来获取 省份信息
后端：
    请求：         不需要请求参数
    业务逻辑：       查询省份信息
    响应：         JSON

    路由：         areas/
    步骤：
        1.查询省份信息
        2.将对象转换为字典数据
        3.返回响应
"""
from apps.areas.models import Area

class Areaview(View):

    def get(self,request):

        # 先查询缓存数据
        province_list = cache.get('province')
        # 如果没有缓存，则查询数据库，并缓存数据

        if province_list is None:
            # 1.查询省份信
            provinces =Area.objects.filter(parent=None)

            # 查询结果集

            # 2.将对象转换为字典数据
            province_list=[]
            for province in provinces:
                province_list.append({
                    'id':province.id,
                    'name':province.name
                })
            # 保存缓存数据
            # cache.set(key,value,expire)
            cache.set('province',province_list,24*3600)

        # 3.返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'province_list': province_list})



"""
需求：
    获取市、区县信息
前端：
    当页面修改省、市的时候，会发送axios请求，来获取 下一级的信息
后端：
    请求：         要传递省份id、市的id
    业务逻辑：       根据id查询信息，将查询结果集转换为字典列表
    响应：         JSON

    路由：         areas/id/
    步骤：
        1.获取省份id、市的id,查询信息
        2.将对象转换为字典数据
        3.返回响应
"""
class SubAreaView(View):

    def get(self,request,id):

        #先获取缓存数据
        data_list = cache.get('city:%s'%id)

        if data_list is None:
        # 1.获取省份id、市的id,查询信息
        # Area.objects.filter(parent_id=id)
        # Area.objects.filter(parent=id)
            up_level =Area.objects.get(id=id)
            down_level = up_level.subs.all()
            # 2讲对象转换成字典数据
            data_list= []
            for item in down_level:
                data_list.append({
                    'id':item.id,
                    'name':item.name

                })

            cache.set('city:%s' % id, data_list, 24 * 3600)
                # 3.返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'sub_data': {'subs': data_list}})





# 举例： 美多商城
# 注册用户 1个亿
# 日活用户 1%     1百万
# 下单比例 1%       1w  10000
#  新增地址的概率 1%   100    300次   2次

# 不经常发生变化的数据 我们最好缓存到redis（内容）中 减少数据库的查询

# 5分钟

class CreateAddressView(LoginRequiredJSONMixin, View):
    """新增地址"""

    def post(self, request):
        """实现新增地址逻辑"""
        # 接收请求
        data = json.loads(request.body.decode())

        # 获取参数,验证参数
        receiver= data.get('receiver')
        province_id=data.get('province_id')
        city_id = data.get('city_id')
        district_id = data.get('district_id')
        place = data.get('place')
        mobile = data.get('mobile')
        tel= data.get('tel')
        email = data.get('email')

        user = request.user

        #2.1验证必穿参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseBadRequest('缺少必传参数')
        #2.2地区的id是否正确
        #2.3详细地址的长度
        #2.4手机号
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('参数tel有误')
        #2.5固定电话
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('参数mobile有误')
        #邮箱
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('参数email有误')
        #数据入库

        address = Address.objects.create(
            user = user,
            title  =receiver,
            province_id = province_id,
            city_id= city_id,
            district_id = district_id,
            place = place,
            mobile = mobile,
            tel = tel,
            email = email,
        )

        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        # 响应保存结果
        return JsonResponse({'code': 0, 'errmsg': '新增地址成功', 'address':'address_dict'})





class ChangePasswordView(LoginRequiredMixin, View):
    """修改密码"""

    def put(self, request):

        """实现修改密码逻辑"""
        # 接收参数
        dict = json.loads(request.body.decode())
        old_password = dict.get('old_password')
        new_password = dict.get('new_password')
        new_password2 = dict.get('new_password2')

        # 校验参数
        if not all([old_password, new_password, new_password2]):
           return http.JsonResponse({'code':400,
                                     'errmsg':'缺少必传参数'})


        result = request.user.check_password(old_password)
        if not result:
            return http.JsonResponse({'code':400,
                                      'errmsg':'原始密码不正确'})

        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
            return http.JsonResponse({'code':400,
                                      'errmsg':'密码最少8位,最长20位'})

        if new_password != new_password2:
            return http.JsonResponse({'code':400,
                                      'errmsg':'两次输入密码不一致'})

        # 修改密码
        try:
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:

            return http.JsonResponse({'code':400,
                                      'errmsg':'修改密码失败'})

        # 清理状态保持信息
        logout(request)

        response = http.JsonResponse({'code':0,
                                      'errmsg':'ok'})

        response.delete_cookie('username')

        # # 响应密码修改结果：重定向到登录界面
        return response
